using System;
using System.Data.Linq;

namespace PropertyExpression.ReactiveRelation.Values
{
    public static class DecimalValue
    {
        public static IValue<decimal> Add(
            this IValue<decimal> value1, IValue<decimal> value2)
        {
            return value1.Func(value2, (x, y) => x + y);
        }

        public static IValue<bool> Greater(
            this IValue<decimal> value1, IValue<decimal> value2)
        {
            return value1.Func(value2, (x, y) => x > y);
        }

        public static IValue<decimal> Sum<TDataSetEntity>(
            this IPropertyValue<EntitySet<TDataSetEntity>> propertyValue,
            Func<IPropertyHolder<TDataSetEntity>, IValue<decimal>> func)
            where TDataSetEntity : class
        {
            return propertyValue.Aggregate(func, () => new Summator());
        }

        private class Summator : IAggregator<decimal, decimal>
        {
            public void Process(decimal arg)
            {
                Result += arg;
            }

            public decimal Result { get; private set; }
        }

        public static IValue<decimal> Minus(
            this IValue<decimal> value1, IValue<decimal> value2)
        {
            return value1.Func(value2, (x, y) => x - y);
        }

        public static IValue<decimal> Mult(
            this IValue<decimal> value1, IValue<decimal> value2)
        {
            return value1.Func(value2, (x, y) => x * y);
        }

        public static IValue<decimal> Div(
            this IValue<decimal> value1, IValue<int> value2)
        {
            return value1.Func(value2, (x, y) => x / y);
        }

        public static IValue<decimal> Div(
            this IValue<decimal> value1, IValue<decimal> value2)
        {
            return value1.Func(value2, (x, y) => x / y);
        }

        public static IValue<decimal> Percent(
            this IValue<decimal> baseValue, IValue<decimal> percentValue)
        {
            return baseValue.Mult(percentValue).Div(100.Const())
                .Func(arg => Math.Round(arg, 2, MidpointRounding.AwayFromZero));
        }
    }
}